import 'dart:async';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sainbainu/common/apis/common_api.dart';
import 'package:sainbainu/common/apis/login_api.dart';
import 'package:sainbainu/common/enums/sms_type.dart';
import 'package:sainbainu/common/http/exception.dart';
import 'package:sainbainu/common/models/request/apple_auth_request.dart';
import 'package:sainbainu/common/models/request/password_login_request.dart';
import 'package:sainbainu/common/models/request/sms_login_request.dart';
import 'package:sainbainu/common/models/request/sms_request.dart';
import 'package:sainbainu/common/repositories/common_repository.dart';
import 'package:sainbainu/common/services/apple.dart';
import 'package:sainbainu/common/services/jpush.dart';
import 'package:sainbainu/common/services/jverify.dart';
import 'package:sainbainu/common/services/user.dart';
import 'package:sainbainu/common/repositories/login_repository.dart';
import 'package:sainbainu/common/routes/routes.dart';
import 'package:sainbainu/common/services/wechat.dart';
import 'package:sainbainu/common/utils/custom_exception.dart';
import 'package:sainbainu/common/utils/encrypt.dart';
import 'package:sainbainu/common/utils/loading.dart';
import 'package:sainbainu/common/values/constant.dart';
import 'package:sainbainu/common/values/settings.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';

import 'index.dart';

class LoginController extends GetxController {
  LoginController();

  final state = LoginState();

  /// 在 widget 内存中分配后立即调用。
  @override
  void onInit() {
    super.onInit();
    state.mobileController = TextEditingController();
    state.codeController = TextEditingController();
    state.pwdController = TextEditingController();
    state.commonRepository = CommonRepository(CommonApi());
    state.loginRepository = LoginRepository(LoginApi());

    /// 预取号
    JverifyService.to.preLogin();

    WechatService.to.isWeChatInstalled.then((flag) {
      state.showWechat.value = flag;
    });
  }

  /// 在 onInit() 之后调用 1 帧。这是进入的理想场所
  @override
  void onReady() {
    super.onReady();
  }

  /// 在 [onDelete] 方法之前调用。
  @override
  void onClose() {
    super.onClose();
    state.mobileController.dispose();
    state.codeController.dispose();
    state.pwdController.dispose();
    state.smsTimer?.cancel();
  }

  /// 切换页面类型
  void switchPageType(PageType pageType) async {
    state.curPageType.value = pageType;
  }

  /// 勾选协议
  void switchAgree(bool value) {
    state.agreeChecked.value = value;
  }

  /// 倒计时
  void runSmsTimer() {
    state.isSending.value = true;
    state.smsTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
      if (state.smsSeconds.value > 0) {
        state.smsSeconds.value--;
      } else {
        timer.cancel();
        state.isSending.value = false;
        state.smsSeconds.value = AppConstant.smsSeconds;
      }
    });
  }

  /// 一键登录
  Future handelEazyLogin() async {
    try {
      LoadingUtil.showLoading();
      await JverifyService.to.authPage();
      await Future.delayed(const Duration(milliseconds: 1500));
      Get.back();
    } on CustomException catch (e) {
      LoadingUtil.showError(e.toString());
    } finally {
      LoadingUtil.dismiss();
    }
  }

  /// 获取验证码
  void sendCode() async {
    if (state.isSending.value) {
      return;
    }
    try {
      if (state.mobileController.text.isEmpty) {
        throw CustomException('请输入手机号码');
      }
      if (state.mobileController.text.length != AppConstant.mobileLength) {
        throw CustomException('手机号长度为${AppConstant.mobileLength}位');
      }
      LoadingUtil.showLoading(text: '获取中...');
      await state.commonRepository.sendSms(SmsRequest(
        mobile: state.mobileController.text,
        type: SmsType.login,
      ));
      LoadingUtil.showSuccess('获取成功'.tr);
      runSmsTimer();
    } on CustomHttpException catch (e) {
      LoadingUtil.showError(e.message);
    } on CustomException catch (e) {
      LoadingUtil.showError(e.toString());
    } catch (e) {
      LoadingUtil.showError('出错啦～');
    }
  }

  /// 验证码登录
  handleSmsCodeLogin() async {
    if (!state.agreeChecked.value) {
      return LoadingUtil.showToast('请阅读并同意协议');
    }
    try {
      if (state.mobileController.text.isEmpty) {
        throw CustomException('请输入手机号码');
      }
      if (state.mobileController.text.length != AppConstant.mobileLength) {
        throw CustomException('手机号长度为${AppConstant.mobileLength}位');
      }
      if (state.codeController.text.isEmpty) {
        throw CustomException('请输入验证码');
      }
      LoadingUtil.showLoading(text: '登录中');
      var rid = await JpushService.to.getRegistrationID();
      var res = await state.loginRepository.smsCodeLogin(SmsLoginRequest(
        mobile: state.mobileController.text,
        code: EncryptUtil.encrypt(state.codeController.text),
        registrationId: rid,
      ));
      loginAfter(res['token'] as String);
      LoadingUtil.showSuccess('登录成功');
    } on CustomHttpException catch (e) {
      LoadingUtil.showError(e.message);
    } on CustomException catch (e) {
      LoadingUtil.showError(e.toString());
    } catch (e) {
      LoadingUtil.showError('出错啦～');
    }
  }

  /// 密码登录
  handlePasswordLogin() async {
    if (!state.agreeChecked.value) {
      return LoadingUtil.showToast('请阅读并同意协议');
    }
    try {
      if (state.mobileController.text.isEmpty) {
        throw CustomException('请输入手机号码');
      }
      if (state.mobileController.text.length != AppConstant.mobileLength) {
        throw CustomException('手机号长度为${AppConstant.mobileLength}位');
      }
      if (state.pwdController.text.isEmpty) {
        throw CustomException('请输入密码');
      }
      if (state.pwdController.text.length < AppConstant.pwdLength) {
        throw CustomException('密码至少${AppConstant.pwdLength}位字符');
      }
      LoadingUtil.showLoading(text: '登录中');
      var rid = await JpushService.to.getRegistrationID();
      var res = await state.loginRepository.passwordLogin(PasswordLoginRequest(
        mobile: state.mobileController.text,
        passwd: EncryptUtil.encrypt(state.pwdController.text),
        registrationId: rid,
      ));
      loginAfter(res['token'] as String);
      LoadingUtil.showSuccess('登录成功');
    } on CustomHttpException catch (e) {
      LoadingUtil.showError(e.message);
    } on CustomException catch (e) {
      LoadingUtil.showError(e.toString());
    } catch (e) {
      LoadingUtil.showError('出错啦～');
    }
  }

  /// 微信登录
  Future<void> handleWeChatLogin() async {
    if (!state.agreeChecked.value) {
      return LoadingUtil.showToast('请阅读并同意协议');
    }
    try {
      LoadingUtil.showLoading();
      await WechatService.to.authCode((String? code) async {
        if (code == null) {
          return LoadingUtil.showError('登录失败！');
        }
        try {
          var rid = await JpushService.to.getRegistrationID();
          var res = await state.loginRepository.wechatLogin(
            code: code,
            registrationId: rid,
          );
          loginAfter(res['token'] as String);
          bool bindedMobile = res['is_mobile'] as bool;
          if (!bindedMobile) {
            Get.toNamed(AppRoutes.bindMobile);
          }
          LoadingUtil.showSuccess('登录成功');
        } on CustomHttpException catch (e) {
          LoadingUtil.showError(e.message);
        } catch (e) {
          LoadingUtil.showError('出错啦～');
        }
      }, (err) {
        LoadingUtil.showError('登录失败！');
      });
    } on CustomException catch (e) {
      LoadingUtil.showError(e.toString());
    } catch (e) {
      LoadingUtil.showError('登录失败！');
    }
  }

  /// apple 登录
  void handleAppleLogin() async {
    if (!state.agreeChecked.value) {
      return LoadingUtil.showToast('请阅读并同意协议');
    }
    try {
      LoadingUtil.showLoading(text: '登录中');
      final rid = await JpushService.to.getRegistrationID();
      final credential = await AppleService.to.appleAuth();
      final res = await state.loginRepository.appleLogin(
        appleAuthRequest: AppleAuthRequest(
          userIdentifier: credential.userIdentifier,
          identityToken: credential.identityToken,
          authorizationCode: credential.authorizationCode,
          givenName: credential.givenName,
        ),
        registrationId: rid,
      );
      loginAfter(res['token'] as String);
      LoadingUtil.showSuccess('登录成功');
      bool bindedMobile = res['is_mobile'] as bool;
      if (!bindedMobile) {
        Get.toNamed(AppRoutes.bindMobile);
      }
      LoadingUtil.showSuccess('登录成功');
    } on CustomHttpException catch (e) {
      LoadingUtil.showError(e.message);
    } on CustomException catch (e) {
      LoadingUtil.showError(e.toString());
    } on SignInWithAppleAuthorizationException catch (e) {
      if (e.code != AuthorizationErrorCode.canceled) {
        LoadingUtil.showError('apple 授权失败！');
      } else {
        LoadingUtil.dismiss();
      }
    } catch (e) {
      LoadingUtil.showError('出错啦～');
    }
  }

  /// 临时登录
  void handleTempLogin() async {
    if (!state.agreeChecked.value) {
      return LoadingUtil.showToast('请阅读并同意协议');
    }
    try {
      LoadingUtil.showLoading(text: '登录中');
      String token = await state.loginRepository.tempLogin(1);
      loginAfter(token);
      LoadingUtil.showSuccess('登录成功');
    } on CustomHttpException catch (e) {
      LoadingUtil.showError(e.message);
    } on CustomException catch (e) {
      LoadingUtil.showError(e.toString());
    } catch (e) {
      LoadingUtil.showError('出错啦～');
    }
  }

  /// 登录之后
  loginAfter(String token) {
    UserService.to.setIsLogin(true);
    UserService.to.setToken(token);
    UserService.to.getAccountInfo();

    if (Get.previousRoute == AppRoutes.welcome || Get.previousRoute.isEmpty) {
      Get.offAllNamed(AppRoutes.layout);
    } else {
      Get.back();
    }
  }
}
